package service

import (
	"awesomeProject/app/model"
	"awesomeProject/app/request"
	"awesomeProject/app/response"
	"awesomeProject/global"
	"awesomeProject/util"
	"context"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"time"
)

type ShipmentSrv struct{}

func (s *ShipmentSrv) Pagination(req request.ShipmentPagination, shopIds []uint, operator model.User) response.Resp {
	offset := (req.PageIndex - 1) * req.PageSize
	filter := bson.D{}
	if req.ShopId != 0 {
		filter = append(filter, bson.E{Key: "shop_id", Value: req.ShopId})
	} else {
		if req.CompanyId != 0 && operator.SuperAdmin {
			var accounts []model.Account
			err := global.Gorm.Where("company_id=? and status=1", req.CompanyId).Find(&accounts).Error
			if err != nil {
				return response.ErrQuery
			}
			shopIds = []uint{}
			for _, account := range accounts {
				shopIds = append(shopIds, account.ShopId)
			}
		}
		if len(shopIds) > 0 {
			filter = append(filter, bson.E{Key: "shop_id", Value: bson.M{"$in": shopIds}})
		}
	}
	if req.ShipmentStatus != 0 {
		filter = append(filter, bson.E{Key: "shipmentStatus", Value: req.ShipmentStatus})
	}
	if req.FulfillmentCenterId != "" {
		filter = append(filter, bson.E{Key: "fulfillmentCenterId", Value: req.FulfillmentCenterId})
	}
	if req.ShipmentId != "" {
		filter = append(filter, bson.E{Key: "shipmentId", Value: req.ShipmentId})
	}
	if req.TrackingNo != "" {
		filter = append(filter, bson.E{Key: "trackingNo", Value: req.TrackingNo})
	}
	if req.SkuId != "" {
		filter = append(filter, bson.E{Key: "skuId", Value: req.SkuId})
	}
	if req.Exception != -1 {
		filter = append(filter, bson.E{Key: "receiveTags", Value: bson.M{"$not": bson.M{"$size": 0}}})
	}

	match := bson.D{{
		"$match", filter,
	}}
	sort := bson.D{{"$sort", bson.M{"createdAt": -1}}}
	skip := bson.D{{"$skip", offset}}
	limit := bson.D{{"$limit", req.PageSize}}
	cursor, err := global.MongoDB.Collection("shipments").Aggregate(context.TODO(), mongo.Pipeline{match, sort, skip, limit})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var shipments []model.Shipment
	if err = cursor.All(context.TODO(), &shipments); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	if len(shipments) == 0 {
		return response.OK.WithData(map[string]interface{}{
			"total": 0,
			"list":  shipments,
		})
	}
	count := bson.D{{"$count", "total"}}
	countCursor, err := global.MongoDB.Collection("shipments").Aggregate(context.TODO(), mongo.Pipeline{match, count})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var countResult []map[string]int
	if err = countCursor.All(context.TODO(), &countResult); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}

	var shipmentsExtra []model.ShipmentWithExtra
	if len(shipments) > 0 {
		for _, shipment := range shipments {
			shipmentExtra := model.ShipmentWithExtra{}
			util.StructAssign(&shipmentExtra, &shipment)

			// ------ 订单进度 begin -------
			//global.LoggerOut(shipmentExtra.ShipmentId)
			var shipmentShipmentsProcess *model.ShipmentShipmentProcess
			shipmentShipmentProcess := model.ShipmentShipmentProcess{}

			//filter := bson.D{{"shipmentId", shipmentExtra.ShipmentId}}
			//filter := bson.D{bson.E{Key: "shipmentId", Value: shipmentExtra.ShipmentId}}

			filter := bson.D{}
			filter = append(filter, bson.E{Key: "shipmentId", Value: shipmentExtra.ShipmentId})
			match := bson.D{{"$match", filter}}
			sort := bson.D{{"$sort", bson.M{"processDate": -1, "id": -1, "sort": 1}}}
			skip := bson.D{{"$skip", 0}}
			limit := bson.D{{"$limit", 1}}

			var shipmentProcess []model.ShipmentProcess
			cursor, err := global.MongoDB.Collection(model.ShipmentProcess{}.TableName()).Aggregate(context.TODO(), mongo.Pipeline{match, sort, skip, limit})
			if err = cursor.All(context.TODO(), &shipmentProcess); err != nil {
				return response.ErrQuery.SetMsg(err.Error())
			}
			if len(shipmentProcess) > 0 {
				for _, op := range shipmentProcess {
					//global.LoggerOut(op.UpdateAt)
					//global.LoggerOut(op.ProcessDate)
					var updateAtOverTime string  // 未跟踪提示
					//if op.UpdateAt.IsZero() {
					//	updateAtOverTime = "未跟踪"
					//} else {
					//	if op.UpdateAt.Add(time.Duration(3) * 24 * time.Hour).Before(time.Now().UTC()) {
					//		updateAtOverTime = "超过3天未跟踪"
					//	} else if op.UpdateAt.Add(time.Duration(1) * 24 * time.Hour).Before(time.Now().UTC()) {
					//		updateAtOverTime = "超过24H未跟踪"
					//	}
					//}

					if op.ProcessDate == "" {
						updateAtOverTime = "未跟踪"
					} else {
						layout := "2006-01-02 15:04:05"
						ProcessAt, _ := time.Parse(layout, op.ProcessDate + " 23:59:59")
						if ProcessAt.Add(time.Duration(3) * 24 * time.Hour).Before(time.Now()) {
							updateAtOverTime = "超过3天未跟踪"
						} else if ProcessAt.Add(time.Duration(1) * 24 * time.Hour).Before(time.Now()) {
							updateAtOverTime = "超过24H未跟踪"
						}
					}

					shipmentShipmentProcess.LastUpdateUser = op.UpdateUser
					shipmentShipmentProcess.LastUpdateAt = op.UpdateAt
					shipmentShipmentProcess.LastProcessDate = op.ProcessDate
					shipmentShipmentProcess.LastProcessContent = op.ProcessContent
					shipmentShipmentProcess.UpdateAtOverTime = updateAtOverTime
					shipmentShipmentsProcess = &shipmentShipmentProcess
					break
				}
			}
			shipmentExtra.ShipmentShipmentProcess = shipmentShipmentsProcess
			// ------ 订单进度 end -------

			shipmentsExtra = append(shipmentsExtra, shipmentExtra)
		}
	}


	return response.OK.WithData(map[string]interface{}{
		"total": countResult[0]["total"],
		//"list":  shipments,
		"list":  shipmentsExtra,
	})
}

func (s *ShipmentSrv) DetailView(req request.ShipmentDetailView) response.Resp {
	filter := bson.D{{"shop_id", req.ShopId}, {"shipmentId", req.ShipmentId}}
	fmt.Println(filter)
	var detail model.ShipmentDetailView
	err := global.MongoDB.Collection("shipment_detail").FindOne(context.TODO(), filter).Decode(&detail)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}

	return response.OK.WithData(detail)
}

func (s *ShipmentSrv) ShipmentTrackBoxView(req request.ShipmentTrackBoxView) response.Resp {
	filter := bson.D{{"shop_id", req.ShopId}, {"shipmentId", req.ShipmentId}}
	match := bson.D{{"$match", filter}}
	cursor, err := global.MongoDB.Collection("track_box_view").Aggregate(context.TODO(), mongo.Pipeline{match})
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}
	var detail []model.ShipmentTrackBoxView
	if err = cursor.All(context.TODO(), &detail); err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}

	return response.OK.WithData(detail)
}

func (s *ShipmentSrv) ShipmentReceivedDetailView(req request.ShipmentReceivedDetailView) response.Resp {
	filter := bson.D{{
		"shop_id", req.ShopId},
		{"shipmentId", req.ShipmentId},
	}
	if req.BoxNumber != "" {
		filter = append(filter, bson.E{Key: "boxNumber", Value: req.BoxNumber})
	}
	if req.TabFilter != "all" && req.TabFilter != "" {
		filter = append(filter, bson.E{Key: "skus.receiveTags", Value: req.TabFilter})
	}
	var detail model.ShipmentReceivedDetailView
	err := global.MongoDB.Collection("received_detail_view").FindOne(context.TODO(), filter).Decode(&detail)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}

	return response.OK.WithData(detail)
}

func (s *ShipmentSrv) ShipmentBoxView(req request.ShipmentBoxView) response.Resp {
	filter := bson.D{{
		"shop_id", req.ShopId},
		{"shipmentId", req.ShipmentId},
	}
	if req.BoxNumber != "" {
		filter = append(filter, bson.E{Key: "boxNumber", Value: req.BoxNumber})
	}
	var detail model.ShipmentBoxView
	err := global.MongoDB.Collection("box_view").FindOne(context.TODO(), filter).Decode(&detail)
	if err != nil {
		return response.ErrQuery.SetMsg(err.Error())
	}

	return response.OK.WithData(detail)
}
